from typing import Callable, List, Optional
from fastapi import Request, HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session

from app.models import get_db
from app.models.user import User
from app.services.user_service import UserService
from app.utils.jwt_util import decode_access_token

security = HTTPBearer()

def has_permission(required_permission: str, auto_error: bool = True):
    """
    权限验证装饰器
    
    Args:
        required_permission: 需要的权限编码
        auto_error: 是否自动抛出异常
    """
    async def permission_dependency(
        credentials: HTTPAuthorizationCredentials = Depends(security),
        db: Session = Depends(get_db)
    ):
        # 解码令牌，获取用户信息
        token = credentials.credentials
        payload = decode_access_token(token)
        user_id = payload.get("user_id")
        
        if not user_id:
            if auto_error:
                raise HTTPException(status_code=401, detail="无效的认证凭据")
            return False
        
        # 获取用户
        user = UserService.get_user_by_id(db, user_id)
        
        # 检查用户角色是否有超级管理员角色
        for role in user.roles:
            if role.code == "ROLE_ADMIN":
                return True
            
            # 检查角色是否有所需权限
            for permission in role.permissions:
                if permission.code == required_permission:
                    return True
        
        if auto_error:
            raise HTTPException(status_code=403, detail="权限不足")
        return False
    
    return permission_dependency

def has_any_permission(required_permissions: List[str], auto_error: bool = True):
    """
    验证是否拥有任一所需权限
    
    Args:
        required_permissions: 所需权限编码列表
        auto_error: 是否自动抛出异常
    """
    async def permission_dependency(
        credentials: HTTPAuthorizationCredentials = Depends(security),
        db: Session = Depends(get_db)
    ):
        # 解码令牌，获取用户信息
        token = credentials.credentials
        payload = decode_access_token(token)
        user_id = payload.get("user_id")
        
        if not user_id:
            if auto_error:
                raise HTTPException(status_code=401, detail="无效的认证凭据")
            return False
        
        # 获取用户
        user = UserService.get_user_by_id(db, user_id)
        
        # 检查用户角色是否有超级管理员角色
        for role in user.roles:
            if role.code == "ROLE_ADMIN":
                return True
            
            # 检查角色是否有任一所需权限
            for permission in role.permissions:
                if permission.code in required_permissions:
                    return True
        
        if auto_error:
            raise HTTPException(status_code=403, detail="权限不足")
        return False
    
    return permission_dependency

def has_all_permissions(required_permissions: List[str], auto_error: bool = True):
    """
    验证是否拥有所有所需权限
    
    Args:
        required_permissions: 所需权限编码列表
        auto_error: 是否自动抛出异常
    """
    async def permission_dependency(
        credentials: HTTPAuthorizationCredentials = Depends(security),
        db: Session = Depends(get_db)
    ):
        # 解码令牌，获取用户信息
        token = credentials.credentials
        payload = decode_access_token(token)
        user_id = payload.get("user_id")
        
        if not user_id:
            if auto_error:
                raise HTTPException(status_code=401, detail="无效的认证凭据")
            return False
        
        # 获取用户
        user = UserService.get_user_by_id(db, user_id)
        
        # 检查用户角色是否有超级管理员角色
        for role in user.roles:
            if role.code == "ROLE_ADMIN":
                return True
        
        # 获取用户所有权限
        user_permissions = set()
        for role in user.roles:
            for permission in role.permissions:
                user_permissions.add(permission.code)
        
        # 检查用户是否拥有所有所需权限
        if set(required_permissions).issubset(user_permissions):
            return True
        
        if auto_error:
            raise HTTPException(status_code=403, detail="权限不足")
        return False
    
    return permission_dependency
